package IC.AST.SemanticAnalysis;

import IC.AST.*;
import IC.Error.ErrorStack;
import IC.Error.ErrorStringIntervaled;
import IC.Error.Error.ErrorType;

abstract public class UnreachableCodeVisitor extends Visitor 
{
	protected String _classID, _funcName;
	

	public Object Visit(Program rootNode) { return VisitSons(rootNode); }
	
	public Object Visit(ClassDeclaration node)
	{
		_classID = node.GetID();
		return VisitSons(node);
	}
	
	public Object Visit(IfStatement node)
	{
		boolean ret = node.GetFirstPart().Visit(this) != null;
		ret &= node.GetSecondPart() != null && node.GetSecondPart().Visit(this) != null;
		
		return ret ? true : null;
	}
	
	protected Object CheckForUnreachableCode(ScopeStatement node, String errReason)
	{
		int i = 0;
		for (ASTNode son : node.GetSons())
		{
			if (son.Visit(this) != null)
				break;
			i++;
		}
		
		AddNotReacebleCodeWarrning(node, i + 1, errReason, _funcName, _classID);
		
		return (i == node.GetSons().size()) ? null : true;
	}
	
	protected Object AddNotReacebleCodeWarrning(ScopeStatement node, int retStatement, String reason, String funcName, String classID)
	{
		if(retStatement >= node.GetSons().size())
			return null;
		
		Interval unreachlines = new Interval(node.GetSons().get(retStatement).GetInterval().GetMin(), 
				node.GetSons().get(node.GetSons().size() - 1).GetInterval().GetMax());

		return ErrorStack.Push(new ErrorStringIntervaled(
					ErrorType.SemanticWarning, 
					String.format("Unreachable code after %s statement form line %d to line %d in function '%s' in class '%s'", 
							reason, unreachlines.GetMin(), unreachlines.GetMax(), _funcName, _classID), 
					unreachlines),
					true);
	}

}
